home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / MacPNG Library 1.02 / pngMacSrc 1.02 / PNG Library 0.80 / zLib 0.95 / gzio.c < prev    next >
Encoding:
Text File  |  1995-08-13  |  13.5 KB  |  403 lines  |  [TEXT/KAHL]

  1. w') {
  2.            err = deflateEnd(&(s->stream));
  3.        } else if (s->mode == 'r') {
  4.            err = inflateEnd(&(s->stream));
  5.        }
  6.     }
  7.     if (s->file != NULL && fclose(s->file)) {
  8.         err = Z_ERRNO;
  9.     }
  10.     if (s->z_err < 0) err = s->z_err;
  11.     TRYFREE(s);
  12.     return err;
  13. }
  14.  
  15. /* ===========================================================================
  16.      Opens a gzip (.gz) file for reading or writing. The mode parameter
  17.    is as in fopen ("rb" or "wb"). The file is given either by file descritor
  18.    or path name (if fd == -1).
  19.      gz_open return NULL if the file could not be opened or if there was
  20.    insufficient memory to allocate the (de)compression state; errno
  21.    can be checked to distinguish the two cases (if errno is zero, the
  22.    zlib error is Z_MEM_ERROR).
  23. */
  24. local gzFile gz_open (path, mode, fd)
  25.     char *path;
  26.     char *mode;
  27.     int  fd;
  28. {
  29.     int err;
  30.     int level = Z_DEFAULT_COMPRESSION; /* compression level */
  31.     char *p = mode;
  32.     gz_stream *s = (gz_stream *)ALLOC(sizeof(gz_stream));
  33.  
  34.     if (!s) return Z_NULL;
  35.  
  36.     s->stream.zalloc = (alloc_func)0;
  37.     s->stream.zfree = (free_func)0;
  38.     s->stream.next_in = s->inbuf = Z_NULL;
  39.     s->stream.next_out = s->outbuf = Z_NULL;
  40.     s->stream.avail_in = s->stream.avail_out = 0;
  41.     s->file = NULL;
  42.     s->z_err = Z_OK;
  43.     s->z_eof = 0;
  44.     s->crc = crc32(0L, Z_NULL, 0);
  45.     s->msg = NULL;
  46.     s->transparent = 0;
  47.  
  48.     s->path = (char*)ALLOC(strlen(path)+1);
  49.     if (s->path == NULL) {
  50.         return destroy(s), (gzFile)Z_NULL;
  51.     }
  52.     strcpy(s->path, path); /* do this early for debugging */
  53.  
  54.     s->mode = '\0';
  55.     do {
  56.         if (*p == 'r') s->mode = 'r';
  57.         if (*p == 'w') s->mode = 'w';
  58.         if (*p >= '1' && *p <= '9') level = *p - '0';
  59.     } while (*p++);
  60.     if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
  61.     
  62.     if (s->mode == 'w') {
  63.         err = deflateInit2(&(s->stream), level,
  64.                            DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
  65.         /* windowBits is passed < 0 to suppress zlib header */
  66.  
  67.         s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
  68.  
  69.         if (err != Z_OK || s->outbuf == Z_NULL) {
  70.             return destroy(s), (gzFile)Z_NULL;
  71.         }
  72.     } else {
  73.         err = inflateInit2(&(s->stream), -MAX_WBITS);
  74.         s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
  75.  
  76.         if (err != Z_OK || s->inbuf == Z_NULL) {
  77.             return destroy(s), (gzFile)Z_NULL;
  78.         }
  79.     }
  80.     s->stream.avail_out = Z_BUFSIZE;
  81.  
  82.     errno = 0;
  83.     s->file = fd < 0 ? FOPEN(path, mode) : fdopen(fd, mode);
  84.  
  85.     if (s->file == NULL) {
  86.         return destroy(s), (gzFile)Z_NULL;
  87.     }
  88.     if (s->mode == 'w') {
  89.         /* Write a very simple .gz header:
  90.          */
  91.         fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", GZ_MAGIC_1, GZ_MAGIC_2,
  92.                DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
  93.     } else {
  94.         /* Check and skip the header:
  95.          */
  96.         Byte c1 = 0, c2 = 0;
  97.         Byte method = 0;
  98.         Byte flags = 0;
  99.         Byte xflags = 0;
  100.         Byte time[4];
  101.         Byte osCode;
  102.         int c;
  103.  
  104.         s->stream.avail_in = fread(s->inbuf, 1, 2, s->file);
  105.         if (s->stream.avail_in != 2 || s->inbuf[0] != GZ_MAGIC_1
  106.             || s->inbuf[1] != GZ_MAGIC_2) {
  107.             s->transparent = 1;
  108.             return (gzFile)s;
  109.         }
  110.         s->stream.avail_in = 0;
  111.         fscanf(s->file,"%c%c%4c%c%c", &method, &flags, time, &xflags, &osCode);
  112.  
  113.         if (method != DEFLATED || feof(s->file) || (flags & RESERVED) != 0) {
  114.             s->z_err = Z_DATA_ERROR;
  115.             return (gzFile)s;
  116.         }
  117.         if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
  118.             long len;
  119.             fscanf(s->file, "%c%c", &c1, &c2);
  120.             len = c1 + ((long)c2<<8);
  121.             fseek(s->file, len, SEEK_CUR);
  122.         }
  123.         if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
  124.             while ((c = getc(s->file)) != 0 && c != EOF) ;
  125.         }
  126.         if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
  127.             while ((c = getc(s->file)) != 0 && c != EOF) ;
  128.         }
  129.         if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
  130.             fscanf(s->file, "%c%c", &c1, &c2);
  131.         }
  132.         if (feof(s->file)) {
  133.             s->z_err = Z_DATA_ERROR;
  134.         }
  135.     }
  136.     return (gzFile)s;
  137. }
  138.  
  139. /* ===========================================================================
  140.      Opens a gzip (.gz) file for reading or writing.
  141. */
  142. gzFile gzopen (path, mode)
  143.     char *path;
  144.     char *mode;
  145. {
  146.     return gz_open (path, mode, -1);
  147. }
  148.  
  149. /* ===========================================================================
  150.      Associate a gzFile with the file descriptor fd.
  151. */
  152. gzFile gzdopen (fd, mode)
  153.     int fd;
  154.     char *mode;
  155. {
  156.     char name[20];
  157.     sprintf(name, "<fd:%d>", fd); /* for debugging */
  158.  
  159.     return gz_open (name, mode, fd);
  160. }
  161.  
  162. /* ===========================================================================
  163.      Reads the given number of uncompressed bytes from the compressed file.
  164.    gzread returns the number of bytes actually read (0 for end of file).
  165. */
  166. int gzread (file, buf, len)
  167.     gzFile file;
  168.     voidp buf;
  169.     unsigned len;
  170. {
  171.     gz_stream *s = (gz_stream*)file;
  172.  
  173.     if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
  174.  
  175.     if (s->transparent) {
  176.         int n = 0;
  177.         Byte *b = (Byte*)buf;
  178.         /* Copy the first two (non-magic) bytes if not done already */
  179.         while (s->stream.avail_in > 0 && len > 0) {
  180.             *b++ = *s->stream.next_in++;
  181.             s->stream.avail_in--;
  182.             len--; n++;
  183.         }
  184.         if (len == 0) return n;
  185.         return n + fread(b, 1, len, s->file);
  186.     }
  187.     if (s->z_err == Z_DATA_ERROR) return -1; /* bad .gz file */
  188.     if (s->z_err == Z_STREAM_END) return 0;  /* don't read crc as data */
  189.  
  190.     s->stream.next_out = buf;
  191.     s->stream.avail_out = len;
  192.  
  193.     while (s->stream.avail_out != 0) {
  194.  
  195.         if (s->stream.avail_in == 0 && !s->z_eof) {
  196.  
  197.             errno = 0;
  198.             s->stream.avail_in =
  199.                 fread(s->inbuf, 1, Z_BUFSIZE, s->file);
  200.             if (s->stream.avail_in == 0) {
  201.                 s->z_eof = 1;
  202.             } else if (s->stream.avail_in == (uInt)EOF) {
  203.                 s->stream.avail_in = 0;
  204.                 s->z_eof = 1;
  205.                 s->z_err = Z_ERRNO;
  206.                 break;
  207.             }
  208.             s->stream.next_in = s->inbuf;
  209.         }
  210.         s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
  211.  
  212.         if (s->z_err == Z_STREAM_END ||
  213.             s->z_err != Z_OK  || s->z_eof) break;
  214.     }
  215.     len -= s->stream.avail_out;
  216.     s->crc = crc32(s->crc, buf, len);
  217.     return (int)len;
  218. }
  219.  
  220. /* ===========================================================================
  221.      Writes the given number of uncompressed bytes into the compressed file.
  222.    gzwrite returns the number of bytes actually written (0 in case of error).
  223. */
  224. int gzwrite (file, buf, len)
  225.     gzFile file;
  226.     voidp buf;
  227.     unsigned len;
  228. {
  229.     gz_stream *s = (gz_stream*)file;
  230.  
  231.     if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
  232.  
  233.     s->stream.next_in = buf;
  234.     s->stream.avail_in = len;
  235.  
  236.     while (s->stream.avail_in != 0) {
  237.  
  238.         if (s->stream.avail_out == 0) {
  239.  
  240.             s->stream.next_out = s->outbuf;
  241.             if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
  242.                 s->z_err = Z_ERRNO;
  243.                 break;
  244.             }
  245.             s->stream.avail_out = Z_BUFSIZE;
  246.         }
  247.         s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
  248.         if (s->z_err != Z_OK) break;
  249.     }
  250.     s->crc = crc32(s->crc, buf, len);
  251.  
  252.     return (int)(len - s->stream.avail_in);
  253. }
  254.  
  255. /* ===========================================================================
  256.      Flushes all pending output into the compressed file. The parameter
  257.    flush is as in the deflate() function.
  258.      gzflush should be called only when strictly necessary because it can
  259.    degrade compression.
  260. */
  261. int gzflush (file, flush)
  262.     gzFile file;
  263.     int flush;
  264. {
  265.     uInt len;
  266.     int done = 0;
  267.     gz_stream *s = (gz_stream*)file;
  268.  
  269.     if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
  270.  
  271.     s->stream.avail_in = 0; /* should be zero already anyway */
  272.  
  273.     for (;;) {
  274.         len = Z_BUFSIZE - s->stream.avail_out;
  275.  
  276.         if (len != 0) {
  277.             if (fwrite(s->outbuf, 1, len, s->file) != len) {
  278.                 s->z_err = Z_ERRNO;
  279.                 return Z_ERRNO;
  280.             }
  281.             s->stream.next_out = s->outbuf;
  282.             s->stream.avail_out = Z_BUFSIZE;
  283.         }
  284.         if (done) break;
  285.         s->z_err = deflate(&(s->stream), flush);
  286.  
  287.         /* deflate has finished flushing only when it hasn't used up
  288.          * all the available space in the output buffer: 
  289.          */
  290.         done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
  291.  
  292.         if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
  293.     }
  294.     fflush(s->file);
  295.     return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
  296. }
  297.  
  298. /* ===========================================================================
  299.    Outputs a long in LSB order to the given file
  300. */
  301. local void putLong (file, x)
  302.     FILE *file;
  303.     uLong x;
  304. {
  305.     int n;
  306.     for (n = 0; n < 4; n++) {
  307.         fputc((int)(x & 0xff), file);
  308.         x >>= 8;
  309.     }
  310. }
  311.  
  312. /* ===========================================================================
  313.    Reads a long in LSB order from the given buffer
  314. */
  315. local uLong getLong (buf)
  316.     Bytef *buf;
  317. {
  318.     uLong x = 0;
  319.     Bytef *p = buf+4;
  320.  
  321.     do {
  322.         x <<= 8;
  323.         x |= *--p; 
  324.     } while (p != buf);
  325.     return x;
  326. }
  327.  
  328. /* ===========================================================================
  329.      Flushes all pending output if necessary, closes the compressed file
  330.    and deallocates all the (de)compression state.
  331. */
  332. int gzclose (file)
  333.     gzFile file;
  334. {
  335.     uInt n;
  336.     int err;
  337.     gz_stream *s = (gz_stream*)file;
  338.  
  339.     if (s == NULL) return Z_STREAM_ERROR;
  340.  
  341.     if (s->mode == 'w') {
  342.         err = gzflush (file, Z_FINISH);
  343.         if (err != Z_OK) return destroy(file);
  344.  
  345.         putLong (s->file, s->crc);
  346.         putLong (s->file, s->stream.total_in);
  347.  
  348.     } else if (s->mode == 'r' && s->z_err == Z_STREAM_END) {
  349.  
  350.         /* slide CRC and original size if they are at the end of inbuf */
  351.         if ((n = s->stream.avail_in) < 8  && !s->z_eof) {
  352.             Byte *p = s->inbuf;
  353.         Bytef *q = s->stream.next_in;
  354.             while (n--) { *p++ = *q++; };
  355.  
  356.             n = s->stream.avail_in;
  357.             n += fread(p, 1, 8, s->file);
  358.             s->stream.next_in = s->inbuf;
  359.         }
  360.         /* check CRC and original size */
  361.         if (n < 8 ||
  362.             getLong(s->stream.next_in) != s->crc ||
  363.             getLong(s->stream.next_in + 4) != s->stream.total_out) {
  364.  
  365.             s->z_err = Z_DATA_ERROR;
  366.         }
  367.     }
  368.     return destroy(file);
  369. }
  370.  
  371. /* ===========================================================================
  372.      Returns the error message for the last error which occured on the
  373.    given compressed file. errnum is set to zlib error number. If an
  374.    error occured in the file system and not in the compression library,
  375.    errnum is set to Z_ERRNO and the application may consult errno
  376.    to get the exact error code.
  377. */
  378. char*  gzerror (file, errnum)
  379.     gzFile file;
  380.     int *errnum;
  381. {
  382.     char *m;
  383.     gz_stream *s = (gz_stream*)file;
  384.  
  385.     if (s == NULL) {
  386.         *errnum = Z_STREAM_ERROR;
  387.         return z_errmsg[1-Z_STREAM_ERROR];
  388.     }
  389.     *errnum = s->z_err;
  390.     if (*errnum == Z_OK) return "";
  391.  
  392.     m =  *errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg;
  393.  
  394.     if (m == NULL || *m == '\0') m = z_errmsg[1-s->z_err];
  395.  
  396.     TRYFREE(s->msg);
  397.     s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
  398.     strcpy(s->msg, s->path);
  399.     strcat(s->msg, ": ");
  400.     strcat(s->msg, m);
  401.     return s->msg;
  402. }
  403.